package com.doordu.soa.service.data.service.impl;

import java.util.Date;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.doordu.soa.service.comm.ResultCode;
import com.doordu.soa.service.comm.ResultData;
import com.doordu.soa.service.comm.utils.DateUtils;
import com.doordu.soa.service.data.dao.ParkingDeviceMapper;
import com.doordu.soa.service.data.entity.ParkingDevice;
import com.doordu.soa.service.data.entity.example.ParkingDeviceExample;
import com.doordu.soa.service.data.service.LogSyncService;
import com.doordu.soa.service.data.service.ParkingDeviceService;
import com.doordu.soa.service.data.service.ParkingLotService;
import com.doordu.soa.service.data.service.ParkingWatchhouseService;
import com.doordu.soa.service.data.utils.UploadDataUtils;
import com.doordu.soa.service.data.vo.LogSyncVo;
import com.doordu.soa.service.data.vo.ParkingDeviceVo;
import com.doordu.soa.service.data.vo.ParkingLotVo;
import com.doordu.soa.service.data.vo.ParkingWatchhouseVo;
import com.doordu.soa.service.data.vo.RequestVo;
import com.doordu.soa.service.web.expection.JSONDefineException;
import com.doordu.soa.service.web.service.DataValidService;
/**
 * 停车场设备服务[实现类]
 * @ClassName: ParkingDeviceServiceImpl
 * @Description: 
 * @author xiaoqun.yi yixq@doordu.com  
 * @date 2017年9月14日 下午1:48:47
 * @version V1.0
 */
@Service
public class ParkingDeviceServiceImpl implements ParkingDeviceService {

	private final Logger logger = LoggerFactory.getLogger(ParkingDeviceServiceImpl.class);

	@Autowired
	ParkingDeviceMapper parkingDeviceMapper;

	@Autowired
	LogSyncService logSyncService;
	
	@Autowired
	ParkingLotService parkingLotService;
	
	@Autowired
	ParkingWatchhouseService parkingWatchhouseService;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public ResultData<Object> insertData(ResultData<Object> resultData,RequestVo requestVo, String serviceMethod, String serviceName) throws Exception  {


		String flag = "0";
		String msg = "";
		Integer successCount = 0;
		Integer failCount = 0;
		Short operateType = requestVo.getOperateType();
		Short status = 0;
		Short gzipFlag = requestVo.getGzipFlag();
		Integer companyId = requestVo.getCompanyId();
		String data = requestVo.getData();
		List<ParkingDeviceVo> list = null;
		if (operateType.intValue() == 1) {
			msg = "上报成功";
			ParkingDeviceVo ParkingDeviceVo = null;

			/** 单次-JSON解析判断 */
			try {
				ParkingDeviceVo = JSONObject.parseObject(data, ParkingDeviceVo.class);
			} catch (Exception e) {
				logger.error("", e);
				throw new JSONDefineException("上报数据的data的JSON格式错误");
			}
			/** 单次-参数校验 */
			String errorMsg = DataValidService.checkData(ParkingDeviceVo);
			if (StringUtils.isNotBlank(errorMsg)) {
				flag = "1";
				resultData.setCode(ResultCode.ERROR_DATA_PARAM);
				DataValidService.setReturnData(flag, resultData, errorMsg);
				return resultData;
			}
			ParkingLotVo parkingLotVo=parkingLotService.getByParkingNoAndCompanyId(ParkingDeviceVo.getParkingNo(), companyId);
			if(null==parkingLotVo){
				errorMsg="停车场编号:{"+ParkingDeviceVo.getParkingNo()+"},还未上报";
				flag = "1";
				resultData.setCode(ResultCode.ERROR_DATA_PARAM);
				DataValidService.setReturnData(flag, resultData, errorMsg);
				return resultData;
			}
			ParkingWatchhouseVo parkingWatchhouseVo=parkingWatchhouseService.getByWatchhouseNumberAndCompanyId(ParkingDeviceVo.getWatchhouseNumber(),ParkingDeviceVo.getParkingNo(), companyId);
			if(null==parkingWatchhouseVo){
				errorMsg="岗亭编号:{"+ParkingDeviceVo.getWatchhouseNumber()+"},还未上报";
				flag = "1";
				resultData.setCode(ResultCode.ERROR_DATA_PARAM);
				DataValidService.setReturnData(flag, resultData, errorMsg);
				return resultData;
			}
			ParkingDeviceVo.setParkingId(parkingLotVo.getParkingId());
			ParkingDeviceVo.setWatchhouseId(parkingWatchhouseVo.getWatchhouseId());
			
			boolean isExist = isExist(companyId, ParkingDeviceVo.getDataId(),ParkingDeviceVo.getDeviceType(),ParkingDeviceVo.getSubType());
			/** 单次存在-更新 */
			if (isExist) {
				ParkingDeviceExample example = setParkingDeviceExample(companyId, ParkingDeviceVo);
				ParkingDevice entity = new ParkingDevice();
				BeanUtils.copyProperties(ParkingDeviceVo, entity);
				entity.setCompanyId(companyId);
				entity.setCheckTime(DateUtils.dateStrToDate(DateUtils.DATE_TIME_FMT, ParkingDeviceVo.getCheckTime()+ ":00"));
				try {
					entity.setUpdateTime(new Date());
					parkingDeviceMapper.updateByExampleSelective(entity, example);
					logSyncService.insertLogSync(companyId, null, serviceMethod, serviceName, successCount, failCount, operateType, status, gzipFlag, null, JSONObject.toJSONString(ParkingDeviceVo));
				} catch (Exception e) {
					flag = "1";
					status = 4;
					msg = "本次上报更新失败 :{dataId:" + ParkingDeviceVo.getDataId() + "}";
					logger.error(msg, e);
					logSyncService.insertLogSync(companyId, null, serviceMethod, serviceName, successCount, failCount, operateType, status, gzipFlag, null, JSONObject.toJSONString(ParkingDeviceVo));
					DataValidService.setReturnData(flag, resultData, msg + e.getMessage());
					throw new Exception(msg + e.getMessage());
				}
				DataValidService.setReturnData(flag, resultData, msg);
				return resultData;
			}

			/** 单次不存在-插入 */
			try {
				ParkingDevice entity = new ParkingDevice();
				BeanUtils.copyProperties(ParkingDeviceVo, entity);
				entity.setCompanyId(companyId);
				entity.setCheckTime(DateUtils.dateStrToDate(DateUtils.DATE_TIME_FMT, ParkingDeviceVo.getCheckTime() + ":00"));
				Date now=new Date();
				entity.setCreateTime(now);
				entity.setUpdateTime(now);
				parkingDeviceMapper.insertSelective(entity);
				logSyncService.insertLogSync(companyId, null, serviceMethod, serviceName, successCount, failCount, operateType, status, gzipFlag, null, JSONObject.toJSONString(ParkingDeviceVo));
			} catch (Exception e) {
				flag = "1";
				status = 4;
				msg = "本次上报插入失败 :{dataId:" + ParkingDeviceVo.getDataId() + "}";
				logger.error(msg, e);
				logSyncService.insertLogSync(companyId, null, serviceMethod, serviceName, successCount, failCount, operateType, status, gzipFlag, null, JSONObject.toJSONString(ParkingDeviceVo));
				DataValidService.setReturnData(flag, resultData, msg + e.getMessage());
				throw new Exception(msg + e.getMessage());
			}
			DataValidService.setReturnData(flag, resultData, msg);
			return resultData;
		}

		/** 批次-JSON解析及判断上报条数后写入文件 */
		String dataFile = "";
		try {
			list = JSONArray.parseArray(data, ParkingDeviceVo.class);
			if (list.size() > 1000) {
				msg = "每次最多只能上报1000条数据";
				resultData.setCode(ResultCode.ERROR_DATA_PARAM);
				DataValidService.setReturnData(flag, resultData, msg);
				return resultData;
			}
			dataFile = UploadDataUtils.saveDataToFile(logSyncService.getParentPath(), "lot", data);
		} catch (Exception e) {
			logger.error("", e);
			throw new JSONDefineException("上报数据的data的JSON格式错误");
		}

		/** 写入日志 */
		LogSyncVo logSyncVo = logSyncService.insertLogSync(companyId, null, serviceMethod, serviceName, successCount, failCount, operateType, status, gzipFlag, dataFile, null);

		/**批次- 参数校验 */
		for (int i = 0; i < list.size(); i++) {
			String errorMsg = DataValidService.checkData(list.get(i));
			if (StringUtils.isNotBlank(errorMsg)) {
				msg += "第" + (i + 1) + "行 " + errorMsg + "</br>";
				flag = "1";
				logSyncService.insertLogSyncError(logSyncVo.getLogId(), JSONObject.toJSONString(list.get(i)), errorMsg, (short) 1);
			}
			ParkingLotVo parkingLotVo=parkingLotService.getByParkingNoAndCompanyId(list.get(i).getParkingNo(), companyId);
			if(null==parkingLotVo){
				errorMsg="停车场编号:{"+list.get(i).getParkingNo()+"},还未上报";
				msg += "第" + (i + 1) + "行 " + errorMsg + "</br>";
				flag = "1";
			}else{
				list.get(i).setParkingId(parkingLotVo.getParkingId());
			}
			ParkingWatchhouseVo parkingWatchhouseVo=parkingWatchhouseService.getByWatchhouseNumberAndCompanyId(list.get(i).getWatchhouseNumber(),list.get(i).getParkingNo(), companyId);
			if(null==parkingWatchhouseVo){
				errorMsg="岗亭编号:{"+list.get(i).getWatchhouseNumber()+"},还未上报";
				msg += "第" + (i + 1) + "行 " + errorMsg + "</br>";
				flag = "1";
			}else{
				list.get(i).setWatchhouseId(parkingWatchhouseVo.getWatchhouseId());
			}
		}
		if (flag.equals("1")) {
			DataValidService.setReturnData(flag, resultData, msg);
			return resultData;
		}

		/** 批次-插入/更新 */
		for (int i = 0; i < list.size(); i++) {
			
			boolean isExist = isExist(companyId, list.get(i).getDataId(),list.get(i).getDeviceType(),list.get(i).getSubType());

			/** 批次-数据存在，则更新 */
			if (isExist) {
				ParkingDeviceExample example = setParkingDeviceExample(companyId, list.get(i));
				ParkingDevice entity = new ParkingDevice();
				BeanUtils.copyProperties(list.get(i), entity);
				entity.setCompanyId(companyId);
				try {
					entity.setUpdateTime(new Date());
					parkingDeviceMapper.updateByExampleSelective(entity, example);
				} catch (Exception e) {
					logSyncService.insertLogSyncError(logSyncVo.getLogId(), JSONObject.toJSONString(list.get(i)), e.getMessage(), (short) 3);
					flag = "1";
					msg = "第" + (i + 1) + "行 上报更新失败 :{dataId:" + list.get(i).getDataId() + "}";
					DataValidService.setReturnData(flag, resultData, msg + e.getMessage());
					throw new Exception(msg + e.getMessage());
				}
				continue;
			}

			/** 批次-数据不存在,则插入 */
			try {
				Date now=new Date();
				ParkingDevice entity = new ParkingDevice();
				BeanUtils.copyProperties(list.get(i), entity);
				entity.setCompanyId(companyId);
				entity.setCreateTime(now);
				entity.setUpdateTime(now);
				entity.setCheckTime(DateUtils.dateStrToDate(DateUtils.DATE_TIME_FMT, list.get(i).getCheckTime() + ":00"));
				parkingDeviceMapper.insertSelective(entity);
			} catch (Exception e) {
				logSyncService.insertLogSyncError(logSyncVo.getLogId(), JSONObject.toJSONString(list.get(i)), e.getMessage(), (short) 3);
				flag = "1";
				msg = "第" + (i + 1) + "行上报插入失败 :{dataId:" + list.get(i).getDataId() + "}";
				DataValidService.setReturnData(flag, resultData, msg + e.getMessage());
				throw new Exception(msg + e.getMessage());
			}
		}

		msg = "上报成功";
		logSyncVo.setStatus((short) 3);
		logSyncVo.setSuccessCount(list.size());
		logSyncVo.setFailCount(0);
		logSyncService.update(logSyncVo);
		DataValidService.setReturnData(flag, resultData, msg);
		return resultData;
	}

	@Override
	public boolean isExist(Integer companyId, String dataId,Short deviceType,String subType) {
		ParkingDeviceExample example = new ParkingDeviceExample();
		ParkingDeviceExample.Criteria criteria = example.createCriteria();
		criteria.andCompanyIdEqualTo(companyId);
		criteria.andDataIdEqualTo(dataId);
		criteria.andDeviceTypeEqualTo(deviceType);
		if(StringUtils.isNotBlank(subType)){
			criteria.andSubTypeEqualTo(subType);
		}
		int count = parkingDeviceMapper.countByExample(example);
		if (count > 0) {
			return true;
		} else {
			return false;
		}
	}

	private ParkingDeviceExample setParkingDeviceExample(Integer companyId, ParkingDeviceVo ParkingDeviceVo) {
		ParkingDeviceExample example = new ParkingDeviceExample();
		ParkingDeviceExample.Criteria criteria = example.createCriteria();
		criteria.andCompanyIdEqualTo(companyId);
		criteria.andDataIdEqualTo(ParkingDeviceVo.getDataId());
		criteria.andDeviceTypeEqualTo(ParkingDeviceVo.getDeviceType());
		if(StringUtils.isNotBlank(ParkingDeviceVo.getSubType())){
			criteria.andSubTypeEqualTo(ParkingDeviceVo.getSubType());
		}
		return example;
	}

}
